/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bgu.ppm.gtm.agents;

import bgu.ppm.gtm.base.GameTheoryModel;
import bgu.ppm.gtm.base.ImmutableStrategy;
import bgu.ppm.sim.impl.mas.agents.WhenReceived;
import java.util.LinkedList;

/**
 *
 * @author User
 */
public class ExhaustiveAgent<T extends GameTheoryModel> extends MessageDrivenGameTheoryAgent<T> {

    LinkedList<ImmutableStrategy> currentStrategies;

    @Override
    protected void start() {
        if (isFirstAgent()) {
            forward();
        }
    }

    private void resetCurrentStrategies() {
        currentStrategies = new LinkedList<>();

        for (ImmutableStrategy s : getStrategies()) {
            currentStrategies.add(s);
        }
    }

    @WhenReceived("FORWARD")
    public void forward() {
        resetCurrentStrategies();

        selectStrategy();
    }

    @WhenReceived("BACKWARD")
    public void backward() {
        removeCurrentStrategy();

        if (currentStrategies.isEmpty()) {
            if (isFirstAgent()) {
                broadcast("TERMINATE");

                terminate();
            } else {
                send("BACKWARD").toPreviousAgent();
            }
        } else {
            selectStrategy();
        }
        
        if (currentStrategies.isEmpty()) {
            send("BACKWARD").to(getId() - 1);
        } else {
            
        }
    }
    
    private void selectStrategy() {
        if (isLastAgent()) {
            while (!currentStrategies.isEmpty()) {
                submitCurrentStrategy(currentStrategies.removeFirst());
            }

            send("BACKWARD").toPreviousAgent();
        } else {
            if (!currentStrategies.isEmpty()) {
                submitCurrentStrategy(currentStrategies.removeFirst());
            }

            send("FORWARD").toNextAgent();
        }        
    }

    @WhenReceived("TERMINATE")
    public void _terminate() {
        terminate();
    }
}
